package br.com.skolar.client.framework.view;

import java.util.ArrayList;
import java.util.Collection;

import com.google.gwt.dom.client.Element;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.user.client.ui.HTML;
import com.google.gwt.user.client.ui.HTMLTable;
import com.google.gwt.user.client.ui.HTMLTable.Cell;
import com.google.gwt.user.client.ui.HTMLTable.RowFormatter;
import com.google.gwt.user.client.ui.LazyPanel;
import com.google.gwt.user.client.ui.VerticalPanel;
import com.google.gwt.user.client.ui.Widget;

public abstract class DataWidget<T> extends LazyPanel {
	public static final String DATAGRID = "datagrid";
	public static final String DATAGRID_HEADER = "datagrid-header";
	public static final String DEFAULT_SELECTED_STYLE = "datagrid-selected";
	
	protected abstract void clearTable();
	protected abstract HTMLTable createTable();
	protected abstract void setupHeaders();
	protected abstract Widget[] getData(T element);

	protected VerticalPanel panel;
	protected HTML gridTitle, emptyResultMessage;
	protected HTMLTable table;

	protected ArrayList<T> data;
	protected T selected;
	
	private int headerRows, selectedRow = -1;

	protected DataWidget() { }
	
	@Override
	public Widget createWidget() {
		panel = new VerticalPanel();
		panel.setSpacing(1);

		String title = getGridTitleText();
		if (title!=null) {
			gridTitle = new HTML("<h2>" + title + "</h2>");
			gridTitle.setVisible(false);
			panel.add(gridTitle);
		}
		
		String empty = getEmptyResultMessageText();
		if (empty!=null) {
			emptyResultMessage = new HTML("<p style='padding: 5px; font-weight: bold'>" + empty + "</b>");	
			emptyResultMessage.setVisible(false);
			panel.add(emptyResultMessage);
		}

		table = createTable();
		table.setStyleName(DATAGRID);
		table.addClickHandler(new ClickHandler() {
			@Override
			public void onClick(ClickEvent event) {
				event.stopPropagation();
				Cell cell = table.getCellForEvent(event);
				if (cell!=null) {
					int row = cell.getRowIndex();
					if (row<headerRows)
						return;
					if (row!=selectedRow) {
						selected = data.get(row - headerRows);
						handleSelection(row, cell.getCellIndex());
					}
				}
			}
		});
		panel.add(table);
		
		return panel;
	}
	
	// default implementation: add highlight function for every table
	// as a facility to reading the table
	protected void handleSelection(int row, int col) {
		RowFormatter rf = table.getRowFormatter();
		String currentStyle = rf.getStyleName(row);
		if (currentStyle.equals(DEFAULT_SELECTED_STYLE))
			rf.removeStyleName(row, DEFAULT_SELECTED_STYLE);
		else rf.setStyleName(row, DEFAULT_SELECTED_STYLE);
	}
	
	public void populate(Collection<T> elements) {
		setVisible(true);
		data = new ArrayList(elements);

		if (gridTitle!=null)
			gridTitle.setVisible(true);

		int size = elements.size();
		boolean hasElements = size > 0;
		
		if (emptyResultMessage!=null)
			emptyResultMessage.setVisible(!hasElements);
		
		if (hasElements) {
			clearTable();
			setupHeaders();
			int i = headerRows = table.getRowCount() - data.size();
			for(T e : elements) {
				Widget data[] = getData(e);
				for (int j=0; j<data.length; j++)
					table.setWidget(i++, j, data[j]);
			}
		}
		table.setVisible(hasElements);
	}
	
	protected String getEmptyResultMessageText() {
		return null;
	}

	protected String getGridTitleText() {
		return null;
	}

	public void highlightRow(T t) {
		highlightRow(data.indexOf(t), DEFAULT_SELECTED_STYLE);
	}

	public void highlightRow(int row) {
		highlightRow(row, DEFAULT_SELECTED_STYLE);
	}

	public void highlightRow(int row, String style) {
		table.getRowFormatter().addStyleName(row, style);
	}

	public void dehighlightRow(T t) {
		dehighlightRow(data.indexOf(t));
	}
	public void dehighlightRow(int row) {
		dehighlightRow(row, DEFAULT_SELECTED_STYLE);
	}
	public void dehighlightRow(int row, String style) {
		table.getRowFormatter().removeStyleName(row, style);
	}

	public void clearDataFormatting() {
		RowFormatter rf = table.getRowFormatter();
		int n = table.getRowCount();
		for (int i=headerRows; i<n; i++) {
			Element e = rf.getElement(i);
			String clazz = e.getClassName();
			if (!clazz.isEmpty())
				e.removeClassName(clazz);
		}
	}

	public void clear() {
		if (emptyResultMessage!=null)
			emptyResultMessage.setVisible(false);
		if (gridTitle!=null)
			gridTitle.setVisible(false);
		table.setVisible(false);
		clearTable();
	}
	
	protected void cellWidth(int row, int cell, String size) {
		if (table.getRowCount()>0)
			table.getCellFormatter().setWidth(row, cell, size);
	}
}